package cn.kingshion.linkedlist;

public class DoubleLinkedListDemo {

    public static void main(String[] args) {

        //定义多个节点
        Node2 node1 = new Node2(1, "jjx", "jjx");
        Node2 node2 = new Node2(2, "kingshion", "kingshion");
        Node2 node3 = new Node2(3, "ysy", "ysy");
        Node2 node4 = new Node2(4, "yisiyuan", "yisiyuan");
        Node2 node5 = new Node2(5, "jxy", "jxy");
        Node2 node6 = new Node2(6, "jinxiangyu", "jinxiangyu");

        //定义一条双向链表
        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();

        //测试新增节点
//        doubleLinkedList.add(node1);
//        doubleLinkedList.add(node2);
//        doubleLinkedList.add(node3);
//        doubleLinkedList.add(node4);
//        doubleLinkedList.add(node5);
//        doubleLinkedList.add(node6);

//        //输出双向链表
//        doubleLinkedList.list();
//        System.out.println();


        //测试按顺序增加节点到链表中
        doubleLinkedList.addByOreder(node4);
        doubleLinkedList.addByOreder(node1);
        doubleLinkedList.addByOreder(node2);
        doubleLinkedList.addByOreder(node5);
        doubleLinkedList.addByOreder(node6);
        doubleLinkedList.addByOreder(node3);



        //输出排序后的双向链表
        doubleLinkedList.list();
        System.out.println();


        //定义一个要更新的节点
        Node2 node7 = new Node2(5, "xiaoxiangyu", "gangyu");
        //测试更新后的链表
        doubleLinkedList.update(node7);
        //输出双向链表
        doubleLinkedList.list();
        System.out.println();

        //测试删除节点
        doubleLinkedList.delete(6);
        doubleLinkedList.list();
        System.out.println();

    }

}


class DoubleLinkedList {
    //
    private Node2 head = new Node2(0, "", "");

    public Node2 getHead() {
        return head;
    }

    //在链表的末尾新增节点
    public void addByOrederadd(Node2 node) {
        Node2 temp = getHead();

        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        temp.next = node;
        node.pre = temp;
    }

    //按 节点的 no 顺序对节点进行新增
    public void addByOreder(Node2 node){
        Node2 temp = getHead();
        boolean flag = false;
        while (true){
            if(temp.next == null){
                break;
            }
            if(node.no < temp.next.no){
                break;
            }else if(node.no == temp.next.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag){
            System.out.println("节点已经存在链表！无法插入");
        }else {
            //这里要尤其的注意：
            //首先：按照单链表的方法将新增的节点按顺序的打通单向
            //然后：既然是双向链表那么一定要多考虑 pre 的指向性
            // 若新增的节点 node 已经处于最后一个节点，那么 node.next 将不存在 更不会存在 node.next.pre 就会报错空指针异常  所以要进行判断
            // 如果不是最后一个节点 则将后面节点的 pre 指针指向新增的节点 node
            // 最后还要将新增节点的 pre 指针指向 node 前面的 temp 节点
            node.next = temp.next;
            temp.next = node;
            if(node.next != null){
                node.next.pre = node;
            }
            node.pre = temp;

        }
    }

    //更新节点
    public void update(Node2 node) {
        Node2 temp = getHead();
        if (temp.next == null) {
            System.out.println("链表为空，无法修改！");
            return;
        }
        boolean flag = false;
        while (true) {
            if (temp.next == null) {
                return;
            } else if (temp.no == node.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.name = node.name;
            temp.nickname = node.nickname;
        } else {
            System.out.println("没有找到节点为 " + node.no + " 的节点。");
        }
    }

    //删除节点
    public void delete(int no) {
        Node2 temp = getHead().next;
        boolean flag = false;
        if (temp == null) {
            System.out.println("链表为空，无法删除！");
            return;
        }
        while (true) {
            if (temp == null) {
                break;
            } else if (temp.no == no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.pre.next = temp.next;
            //在这里一定要注意判断  所要删除的节点是否为最后一个节点，
            // 如果为最后一个节点的话
            //此时 temp 没有 next 节点，那么就会报错 空指针异常，所以要对是否为末尾进行判断
            // 若为末尾 则直接将末尾前面的（pre）节点的 （next） 节点置空就行了，即完成上一步
            if (temp.next != null) {
                temp.next.pre = temp.pre;
            }
        }
    }

    //打印链表
    public void list() {
        if (getHead().next == null) {
            System.out.println("链表为空！");
        }
        Node2 temp = getHead().next;
        while (temp != null) {
            System.out.println(temp);
            temp = temp.next;
        }

    }
}

/**
 * 定义节点
 * 双向链表的节点相对单向链表多一个 pre 属性
 */
class Node2 {

    public int no;
    public String name;
    public String nickname;
    public Node2 pre;
    public Node2 next;

    public Node2(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    @Override
    public String toString() {
        return "Node2{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}